import { Listbox } from "@headlessui/react";
import "./index.scss";
import Condition, { IfTruthy } from "@/renderer/components/Condition";
import Loading from "@/renderer/components/Loading";
import { isBasicType } from "@/common/normalize-util";
import useVirtualList from "@/hooks/useVirtualList";
import { rem } from "@/common/constant";
import { ReactNode, useRef } from "react";
import SvgAsset from "@/renderer/components/SvgAsset";
import { Tooltip } from "react-tooltip";
import { IAppConfig } from "@/types/app-config";
import useAppConfig from "@/hooks/useAppConfig";
import AppConfig from "@shared/app-config/renderer";

interface ListBoxSettingItemProps<T extends keyof IAppConfig> {
    keyPath: T;
    label?: string;
    options: Array<IAppConfig[T]> | null;
    onChange?: (event: Event, newConfig: IAppConfig[T]) => void;
    renderItem?: (item: IAppConfig[T]) => ReactNode;
    width?: number | string;
    toolTip?: string;
}

export default function ListBoxSettingItem<T extends keyof IAppConfig>(
    props: ListBoxSettingItemProps<T>,
) {

    const {
        keyPath,
        label,
        options,
        onChange,
        renderItem,
        width,
        toolTip,
    } = props;

    const value = useAppConfig(keyPath);

    return (
        <div className="setting-view--list-box-setting-item-container setting-row">
            <IfTruthy condition={toolTip}>
                <Tooltip id={`tt-${keyPath}`}></Tooltip>
            </IfTruthy>
            <Listbox
                value={value}
                onChange={
                    (newVal) => {
                        const event = new Event("ConfigChanged", {
                            cancelable: true,
                        });
                        if (onChange) {
                            onChange(event, newVal);
                        }
                        if (!event.defaultPrevented) {
                            AppConfig.setConfig({
                                [keyPath]: newVal,
                            });
                        }
                    }
                }
            >
                <div className={"label-container"}>
                    {label}
                    <IfTruthy condition={toolTip}>
                        <div
                            className="question-mark-container"
                            data-tooltip-id={`tt-${keyPath}`}
                            data-tooltip-content={toolTip}
                        >
                            <SvgAsset iconName="question-mark-circle"></SvgAsset>
                        </div>
                    </IfTruthy>
                </div>
                <div className="options-container">
                    <Listbox.Button
                        as="div"
                        className={"listbox-button"}
                        style={{ width }}
                    >
                        <span>
                            {renderItem
                                ? renderItem(value)
                                : isBasicType(value)
                                    ? (value as string)
                                    : ""}
                        </span>
                    </Listbox.Button>
                    <Listbox.Options as={"div"}>
                        <ListBoxOptions
                            width={width}
                            options={options}
                            renderItem={renderItem}
                        ></ListBoxOptions>
                    </Listbox.Options>
                </div>
            </Listbox>
        </div>
    );
}

interface IListBoxOptionsProps<T extends keyof IAppConfig> {
    options: Array<IAppConfig[T]> | null;
    renderItem?: (item: IAppConfig[T]) => ReactNode;
    width?: number | string;
}

function ListBoxOptions<T extends keyof IAppConfig>(
    props: IListBoxOptionsProps<T>,
) {
    const { options, renderItem, width } = props;
    const containerRef = useRef<HTMLDivElement>();

    const virtualController = useVirtualList({
        data: options ?? [],
        estimateItemHeight: 2.2 * rem,
        getScrollElement: () => containerRef.current,
        renderCount: 40,
        fallbackRenderCount: 20,
    });

    return (
        <div
            ref={containerRef}
            className={"listbox-options shadow backdrop-color"}
            style={{ width }}
        >
            <Condition condition={options !== null} falsy={<Loading></Loading>}>
                <div
                    style={{
                        position: "relative",
                        height: virtualController.totalHeight,
                    }}
                >
                    {virtualController.virtualItems?.map?.((virtualItem) => (
                        <Listbox.Option
                            className={"listbox-option"}
                            key={virtualItem.rowIndex}
                            value={virtualItem.dataItem}
                            style={{
                                position: "absolute",
                                top: virtualItem.top,
                                width,
                            }}
                            as="div"
                        >
                            <div>
                                {renderItem
                                    ? renderItem(virtualItem.dataItem)
                                    : isBasicType(virtualItem.dataItem)
                                        ? (virtualItem.dataItem as string)
                                        : ""}
                            </div>
                        </Listbox.Option>
                    ))}
                </div>
            </Condition>
        </div>
    );
}
